package com.zimi.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.zimi.bean.Constants;
import com.zimi.mapper.*;
import com.zimi.model.*;
import com.zimi.util.CommonUtil;
import com.zimi.util.ShiroUtils;
import com.zimi.util.UserUtil;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 系统组织机构 Service
 *
 * @author lnintr
 * @since 2019-05-20
 */
@Service
public class SysOrgService {
    @Autowired
    private SysOrgMapper sysOrgMapper;

    @Autowired
    private SysOrgExtendMapper sysOrgExtendMapper;

    @Autowired
    private SysOrgPrivilegeMapper sysOrgPrivilegeMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysPostMapper sysPostMapper;

    @Autowired
    private SysPostPrivilegeMapper sysPostPrivilegeMapper;

    @Autowired
    private SysOrgRoleEmpowerMapper sysOrgRoleEmpowerMapper;

    @Autowired
    private SysRolePrivilegeMapper sysRolePrivilegeMapper;

    @Autowired
    private CommonUtil commonUtil;

    /**
     * author wh
     *
     * @return
     */
    public List<SysOrgExtend> selectRecycleList() {
        List<SysOrgExtend> list = sysOrgExtendMapper.selectRecycleList();
        return list;
    }

    /*
     * 确认恢复的机构有没有删除了的父机构，没有则恢复
     * */
    @Transactional
    public boolean recycle(List<SysOrgExtend> sysOrgList) {
        List<Integer> ids = new ArrayList<>();
        List<Integer> allIds = new ArrayList<>();

        for (SysOrgExtend soe : sysOrgList) {
            allIds.add(soe.getId());

            if (soe.getParentId() > 0) {
                ids.add(soe.getParentId());
            }
        }

        // 1)取出已删除的父机构一览 若有则退出
        if (ids.size() > 0) {
            List<SysOrg> orgs = sysOrgMapper.selectList(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getOrgState, 2).in(SysOrg::getId, ids));

            if (orgs != null && orgs.size() > 0) {
                Session session = ShiroUtils.getSession();
                session.setAttribute(Constants.RECYCLE_SYSORG, sysOrgList);
                return false;
            }
        }

        // 2)恢复所有的机构
        SysUser user = UserUtil.getUser();

        SysOrg sysOrg = new SysOrg().setUpdateUser(user.getId()).setUpdateTime(new Date()).setOrgState(1);
        sysOrgMapper.update(sysOrg, new UpdateWrapper<SysOrg>().lambda().in(SysOrg::getId, allIds));
        return true;
    }

    /*
     * 确认恢复的机构有没有删除了的父机构，没有则恢复
     * */
    @Transactional
    public void recycleConfirm() {
        List<Integer> ognIds = new ArrayList<>();
        List<Integer> allIds = new ArrayList<>();

        // 1)取出已删除的父机构一览 若有则退出
        Session session = ShiroUtils.getSession();
        List<SysOrgExtend> sysOrgList = (List<SysOrgExtend>) session.getAttribute(Constants.RECYCLE_SYSORG);
        session.removeAttribute(Constants.RECYCLE_SYSORG);

        if (sysOrgList != null && sysOrgList.size() > 0) {
            for (SysOrgExtend soe : sysOrgList) {
                allIds.add(soe.getId());
                ognIds.add(soe.getOgnId());
            }

            List<SysOrg> orgs = sysOrgMapper.selectList(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getOrgState, 2).in(SysOrg::getOgnId, ognIds).orderByAsc(SysOrg::getOgnId, SysOrg::getOrgSort));
            if (orgs != null && orgs.size() > 0) {
                Map<Integer, SysOrg> orgMap = new HashMap<>();

                for (SysOrg so : orgs) {
                    orgMap.put(so.getId(), so);
                }

                // 2)取得父机构编号一览
                allIds = getParents(orgMap, allIds);

                // 3)恢复所有的机构
                SysUser user = UserUtil.getUser();

                SysOrg sysOrg = new SysOrg().setUpdateUser(user.getId()).setUpdateTime(new Date()).setOrgState(1);
                sysOrgMapper.update(sysOrg, new UpdateWrapper<SysOrg>().lambda().in(SysOrg::getId, allIds));
            }
        }
    }

    /*
     * 取得父节点编号一览
     * */
    private List<Integer> getParents(Map<Integer, SysOrg> orgMap, List<Integer> ids) {
        List<Integer> result = new ArrayList<>();
        SysOrg tmpOrg = null;
        Map<Integer, Integer> parentMap = new HashMap<>();

        // 1)循环机构编号一览参数
        for (Integer id : ids) {
            result.add(id);

            tmpOrg = orgMap.get(id);

            if (tmpOrg != null && tmpOrg.getOrgPid() > 0) {
                parentMap.put(tmpOrg.getOrgPid(), 1);
            }
        }

        // 2)递归取得父机构编号一览
        if (parentMap.size() > 0) {
            List<Integer> parentIds = new ArrayList<>();

            for (Integer key : parentMap.keySet()) {
                parentIds.add(key);
            }

            result.addAll(getParents(orgMap, parentIds));
        }

        return result;
    }

    /*
     * 取得指定机构分类的机构一览
     * */
    public Object getOrgList(int cateId) {

        //1）先判断当前人登录人是不是超级管理员
        Session session = ShiroUtils.getSession();
        boolean admin = (boolean) session.getAttribute(Constants.IS_ADMIN_FLAG);//是否是超级管理员

        List<SysOrg> result = new ArrayList<>();

        if (admin) {
            result = sysOrgMapper.selectList(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getOrgCate, cateId).eq(SysOrg::getOrgState, 1).orderByAsc(SysOrg::getOrgSort));
        } else {
            //2）根据当前登录人获取可见的orgList
            Map map = commonUtil.getOrgList();

            List<SysOrg> orgList = (List<SysOrg>) map.get("orgList");

            if (orgList != null && orgList.size() > 0) {
                for (SysOrg so : orgList) {
                    if (so.getOrgCate() == cateId) {
                        result.add(so);
                    }
                }
            }
        }
        return result;
    }

    /*
     * 取得组织和角色信息
     * */
    public Object getOrglistByOperator(SysOrgExtend sysOrgExtend) {
        Map map = commonUtil.getOrgList();
        List<SysOrgExtend> list = sysOrgExtendMapper.getMineOrgList(map);

        if (list != null && list.size() > 0) {
            // 4)取得并合并机构分类
            List<SysOrgExtend> orgCateList = sysOrgExtendMapper.getMineOgnCateList((List<Integer>) map.get("ognIdList"));

            if (orgCateList != null && orgCateList.size() > 0) {
                list.addAll(orgCateList);
            }
        }

        return list;
    }

    /**
     * @param org
     * @desc 根据分类id查询单位
     */
    public List<SysOrg> getCompanyByCateIds(SysOrg org, int[] arr) {
        List<Integer> cates = new ArrayList<>();
        for (int i : arr) {
            cates.add(i);
        }

        List<SysOrg> result = new ArrayList<>();
        List<SysOrg> list = null;
        // 1)根据分类id和机构id查出除自身之外的单位列表
        if (org.getOrgName() != null && org.getOrgName() != "") {
            list = new SysOrg().selectList(new LambdaQueryWrapper<SysOrg>().in(SysOrg::getOrgCate, cates).eq(SysOrg::getOrgState, 1).eq(SysOrg::getOrgPid, 0).ne(SysOrg::getOgnId, org.getId()).like(SysOrg::getOrgName, org.getOrgName()));
        } else {
            list = new SysOrg().selectList(new LambdaQueryWrapper<SysOrg>().in(SysOrg::getOrgCate, cates).eq(SysOrg::getOrgState, 1).eq(SysOrg::getOrgPid, 0).ne(SysOrg::getOgnId, org.getId()));
        }

        if (list != null && list.size() > 0) {
            for (SysOrg so : list) {
                //2) 根据单位自身id和单位id去sys_org_partner表中查询关联的单位
                SysOrgPartner partner = new SysOrgPartner().selectOne(new LambdaQueryWrapper<SysOrgPartner>().eq(SysOrgPartner::getOrgId, org.getId()).eq(SysOrgPartner::getTargetOrgId, so.getId()));
                SysOrg sysOrg = new SysOrg();

                // 3)把sys_org_partner表中的id和updateTIme赋给sysOrg对象
                if (partner != null) {
                    //4) 如果partner不为null,则过滤掉state为1的单位
                    if (partner.getState() == 1) {
                        continue;
                    } else {
                        sysOrg.setId(partner.getId());
                        sysOrg.setUpdateTime(partner.getUpdateTime());
                        sysOrg.setOgnId(so.getId());
                        sysOrg.setOrgName(so.getOrgName());
                        sysOrg.setOrgCate(so.getOrgCate());

                        result.add(sysOrg);
                    }
                } else {
                    sysOrg.setId(null);
                    sysOrg.setUpdateTime(null);
                    sysOrg.setOgnId(so.getId());
                    sysOrg.setOrgName(so.getOrgName());
                    sysOrg.setOrgCate(so.getOrgCate());

                    result.add(sysOrg);
                }
            }
        }

        return result;
    }

    @Transactional
    public void insert(SysOrg sysOrg) {
        SysUser sysUser = UserUtil.getUser();

        // 1)没有父节点时
        sysOrgMapper.selectOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getId, sysOrg.getOrgPid()).last("for update"));
        sysOrg.setOrgSort(sysOrgMapper.selectSort(sysOrg.getOrgPid()));

        Date date = new Date();
        sysOrg.setOrgState(1);
        sysOrg.setCreateUser(sysUser.getId());
        sysOrg.setCreateTime(date);
        sysOrg.insert();

        // 2)机构根节点编号
        if (sysOrg.getOrgPid() == 0) {
            sysOrg.setOgnId(sysOrg.getId());
            sysOrg.updateById();
        }
    }

    /**
     * @author wh
     * @desc 切换上级部门
     */
    @Transactional
    public void changeDep(SysOrg org) {
        SysUser user = UserUtil.getUser();
        Date tmpTime = new Date();
        int orgSort = org.getOrgSort();
        int maxSort = 0;

        //1）取出上级部门下的最大sort
        List<SysOrg> list = new SysOrg().selectList(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getOrgPid, org.getOrgPid()).orderByDesc(SysOrg::getOrgSort));

        //2)取最大sort
        if (list != null && list.size() > 0) {
            maxSort = list.get(0).getOrgSort();

            //更新自己同级部门sort比自己大的
            for (SysOrg so : list) {
                if (so.getOrgSort() > orgSort) {
                    so.setOrgSort(orgSort - 1);
                    so.updateById();
                }
            }
        }

        // 3)对自己部门上级加锁，保证其不成为自己的下级
        SysOrg upOrg = new SysOrg().selectOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getId, org.getOrgPid()).last("for update"));

        // 4）对要修改的对象加行锁
        SysOrg result = new SysOrg().selectOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getId, org.getId()).last("for update"));

        // 5）判断orgpid 是否一样，如果一样则抛出异常
        if (org.getOrgPid() == result.getOrgPid()) {
            throw new RuntimeException("修改数据失败，您选择的是自己部门的上级。");
        }

        // 6）判断该数据已经被改过没有
        if (result.getUpdateTime() != null) {
            if (org.getUpdateTime() == null) {
                throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
            } else {
                if (org.getUpdateTime().getTime() != result.getUpdateTime().getTime()) {
                    throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
                }
            }
        }

        //7）更新入库
        org.setOrgSort(maxSort + 1);
        org.setUpdateUser(user.getId());
        org.setUpdateTime(tmpTime);

        org.updateById();
    }

    @Transactional
    public Object update(SysOrg sysOrg) {
        // 1）对要修改的对象加行锁
        SysOrg result = sysOrg.selectOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getId, sysOrg.getId()).last("for update"));

        // 2）判断该数据已经被改过没有
        if (result.getUpdateTime() != null) {
            if (sysOrg.getUpdateTime() == null) {
                throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
            } else {
                if (sysOrg.getUpdateTime().getTime() != result.getUpdateTime().getTime()) {
                    throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
                }
            }
        }

        if (sysOrg.getOpen() != null) {
            List res = new ArrayList();
            List<Integer> list = getChildList(sysOrg.getId(), res); //获取子节点
            if (list != null && list.size() > 0) {
                switch (sysOrg.getOpen()) {
                    case 1:
                        for (int i : list) {
                            SysOrg org = new SysOrg();
                            org.setOpen(1);
                            org.setId(i);
                            org.updateById();
                        }
                        break;
                    case 2:
                        for (int i : list) {
                            SysOrg org = new SysOrg();
                            org.setOpen(3);
                            org.setId(i);
                            org.updateById();
                        }
                        break;
                    case 3:
                        for (int i : list) {
                            SysOrg org = new SysOrg();
                            org.setOpen(3);
                            org.setId(i);
                            org.updateById();
                        }
                        break;
                }
            }
        }

        SysUser user = UserUtil.getUser();
        sysOrg.setUpdateUser(user.getId());
        sysOrg.setUpdateTime(new Date());

        // 3)变更数据
        return sysOrg.updateById();
    }

    /**
     * @author wh
     * @desc 递归根据机构id获取机构子id的集合
     */
    public List<Integer> getChildList(int id, List<Integer> result) {

        List<SysOrg> list = new SysOrg().selectList(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getOrgPid, id));
        if (list != null && list.size() > 0) {
            for (SysOrg i : list) {
                result.add(i.getId());
                this.getChildList(i.getId(), result);
            }
        }
        return result;
    }

    @Transactional
    public void delete(List<SysOrg> sysOrgList) {
        if (sysOrgList.size() > 0) {
            // 1）取得机构的编号一览
            Map<Integer, SysOrg> orgMap = new HashMap<>();
            List<Integer> idList = new ArrayList<>();
            for (SysOrg so : sysOrgList) {
                orgMap.put(so.getId(), so);
                idList.add(so.getId());
            }

            // 2)指定机构下还有人员时
            if (sysOrgExtendMapper.selectUserCountByIds(idList) > 0) {
                throw new RuntimeException("删除数据失败，指定机构下还有用户。");
            }

            // 1）对要修改的对象加行锁
            List<SysOrg> result = sysOrgMapper.selectList(new QueryWrapper<SysOrg>().lambda().in(SysOrg::getId, idList).last("for update"));
            SysOrg tmpOrg = null;

            SysUser user = UserUtil.getUser();
            Date updateTime = new Date();

            // 2）判断该数据已经被改过没有
            if (result != null && result.size() > 0) {
                for (SysOrg so : result) {
                    tmpOrg = orgMap.get(so.getId());

                    // 3）判断该数据已经被改过没有
                    if (so.getUpdateTime() != null) {
                        if (tmpOrg.getUpdateTime() == null) {
                            throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                        } else {
                            if (so.getUpdateTime().getTime() != tmpOrg.getUpdateTime().getTime()) {
                                throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                            }
                        }
                    }
                }

                // 4)删除机构
                SysOrg sysOrg = new SysOrg().setUpdateUser(user.getId()).setUpdateTime(updateTime).setOrgState(2);
                sysOrgMapper.update(sysOrg, new UpdateWrapper<SysOrg>().lambda().in(SysOrg::getId, idList));

                // 5）根据编号一览取得机构的权限，岗位，角色
                List<SysPost> sysPosts = sysPostMapper.selectList(new QueryWrapper<SysPost>().lambda().in(SysPost::getOrgId, idList).eq(SysPost::getPostState, 1));
                List<SysOrgRoleEmpower> roleEmpowers = sysOrgRoleEmpowerMapper.selectList(new QueryWrapper<SysOrgRoleEmpower>().lambda().in(SysOrgRoleEmpower::getOrgId, idList).eq(SysOrgRoleEmpower::getSoreState, 1));

                // 7)删除机构的岗位和关联权限
                if (sysPosts != null && sysPosts.size() > 0) {
                    idList.clear();

                    for (SysPost sp : sysPosts) {
                        idList.add(sp.getId());
                    }

                    // 一次性删除岗位
                    SysPost sysPost = new SysPost().setUpdateUser(user.getId()).setUpdateTime(updateTime).setPostState(2);
                    sysPostMapper.update(sysPost, new UpdateWrapper<SysPost>().lambda().in(SysPost::getOrgId, idList));

                    // 删除对应的岗位权限
                    List<SysPostPrivilege> postPrivileges = sysPostPrivilegeMapper.selectList(new QueryWrapper<SysPostPrivilege>().lambda().in(SysPostPrivilege::getPostId, idList).eq(SysPostPrivilege::getPrivilegeState, 1));

                    if (postPrivileges != null & postPrivileges.size() > 0) {
                        idList.clear();

                        for (SysPostPrivilege sysPostPrivilege : postPrivileges) {
                            idList.add(sysPostPrivilege.getId());
                        }

                        // 一次性删除岗位权限
                        SysPostPrivilege sysPostPrivilege = new SysPostPrivilege().setUpdateUser(user.getId()).setUpdateTime(updateTime).setPrivilegeState(2);
                        sysPostPrivilegeMapper.update(sysPostPrivilege, new UpdateWrapper<SysPostPrivilege>().lambda().in(SysPostPrivilege::getId, idList));
                    }
                }

                // 8)删除机构的角色关联
                if (roleEmpowers != null && roleEmpowers.size() > 0) {
                    idList.clear();

                    for (SysOrgRoleEmpower sore : roleEmpowers) {
                        idList.add(sore.getId());
                    }

                    // 一次性删除机构的角色关联
                    SysOrgRoleEmpower sysOrgRoleEmpower = new SysOrgRoleEmpower().setUpdateUser(user.getId()).setUpdateTime(updateTime).setSoreState(2);
                    sysOrgRoleEmpowerMapper.update(sysOrgRoleEmpower, new UpdateWrapper<SysOrgRoleEmpower>().lambda().in(SysOrgRoleEmpower::getId, idList));
                }
            }
        }
    }


    @Transactional
    public int move(List<SysOrg> sysOrgIdList) {
        Map<Integer, SysOrg> orgMap = new HashMap<>();
        // 1）对要修改的对象数据数量进行验证
        if (sysOrgIdList.size() != 2) {
            throw new RuntimeException("提交的关于交换顺序的数据不正确。");
        }

        // 2）对要修改的对象加行锁
        List<Integer> idList = new ArrayList<>();
        for (SysOrg so : sysOrgIdList) {
            orgMap.put(so.getId(), so);
            idList.add(so.getId());
        }

        List<SysOrg> result = sysOrgMapper.selectList(new QueryWrapper<SysOrg>().lambda().in(SysOrg::getId, idList).last("for update"));

        if (result == null || result.size() != 2) {
            throw new RuntimeException("服务器关于交换顺序的数据异常。");
        }

        SysOrg tmpOrg = null;

        SysUser user = UserUtil.getUser();
        Date updateTime = new Date();

        for (SysOrg so : result) {
            tmpOrg = orgMap.get(so.getId());

            // 3）判断该数据已经被改过没有
            if (so.getUpdateTime() != null) {
                if (tmpOrg.getUpdateTime() == null) {
                    throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                } else {
                    if (so.getUpdateTime().getTime() != tmpOrg.getUpdateTime().getTime()) {
                        throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                    }
                }
            }

            // 4)变更数据
            tmpOrg.setUpdateUser(user.getId());
            tmpOrg.setUpdateTime(updateTime);
            tmpOrg.updateById();
        }

        return 0;
    }

    /**
     * @author wh
     * @desc 根据部门id获取分类机构树
     */
    public List<SysOrgExtend> getOrgTreeById(int id) {
        List<SysOrgExtend> result = new ArrayList<>();
        SysOrgExtend tmpExtend = null;

        //1)先获取分类
        List<SysOrgCate> cates = new SysOrgCate().selectList(new LambdaQueryWrapper<SysOrgCate>().eq(SysOrgCate::getSocState, 1));

        //2)把分类添加给result
        if (cates != null && cates.size() > 0) {
            for (SysOrgCate soc : cates) {
                tmpExtend = new SysOrgExtend();

                tmpExtend.setId(soc.getId());
                tmpExtend.setOrgCateId(soc.getId());
                tmpExtend.setFlag(1);
                tmpExtend.setOrgName(soc.getSocName());
                tmpExtend.setUpdateTime(soc.getUpdateTime());

                result.add(tmpExtend);
            }
        }

        //3)获取除自身和子机构的集合
        List<Integer> idList = new ArrayList<>();
        //(1)递归获取子机构id集合
        List<Integer> ids = getChildList(id, idList);
        //(2)把自身id加入集合
        ids.add(id);
        //(3)取出所有机构
        List<SysOrg> orgs = new SysOrg().selectList(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getOrgState, 1));
        //(4)剔除自身和自己的子机构
        if (orgs != null && orgs.size() > 0 && ids != null && ids.size() > 0) {
            for (SysOrg so : orgs) {
                //4)把自身及子机构以外的机构添加给result
                if (!ids.contains(so.getId())) {
                    tmpExtend = new SysOrgExtend();

                    tmpExtend.setParentId(so.getOrgPid());
                    tmpExtend.setId(so.getId());
                    tmpExtend.setOrgId(so.getId());
                    tmpExtend.setOgnId(so.getOgnId());
                    tmpExtend.setOrgCateId(so.getOrgCate());
                    tmpExtend.setFunctionId(so.getOrgSort()); //fucntionId作为orgSort存放
                    tmpExtend.setFlag(2);
                    tmpExtend.setOrgName(so.getOrgName());
                    tmpExtend.setName(so.getOrgName());
                    tmpExtend.setUpdateTime(so.getUpdateTime());

                    result.add(tmpExtend);
                }
            }
        }

        return result;
    }

}

